﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

using WinForms = System.Windows.Forms;
using System.Windows.Markup;
using System.IO;

using Jarvis.Analytics;
using Jarvis.Learners;
using Jarvis.Sensors;
using Jarvis.Utility;
using Jarvis.Windows;

namespace Jarvis
{
    public partial class App : Application
    {
        private WinForms.NotifyIcon notifier = new WinForms.NotifyIcon();

        public SensorWindow sensorWindow = null;
        public AboutWindow aboutWindow = null;
        public CorrectPredictionsWindow correctWindow = null;
        public PredictionsWindow predictionWindow = null;
        public PreferencesWindow preferencesWindow = null;
        public LearnersWindow learnersWindow = null;
        public RulesWindow rulesWindow = null;

        public Dictionary<string, string> predictions;

        public App()
        {
            this.InitializeComponent();

            ResourceDictionary resources = this.Resources;

            foreach (DictionaryEntry entry in resources)
            {
                Console.WriteLine("Loaded " + entry.Key);
            }

            this.notifier.MouseDown += new WinForms.MouseEventHandler(notifier_MouseDown);

            this.notifier.Icon = Icon.FromHandle(Jarvis.Properties.Resources.systray_bell.GetHicon());
            this.notifier.Visible = true;

            this.aboutWindow = new AboutWindow();
            
            this.correctWindow = new CorrectPredictionsWindow();
            this.correctWindow.app = this;

            this.predictionWindow = new PredictionsWindow();
            this.preferencesWindow = new PreferencesWindow();
            this.learnersWindow = new LearnersWindow();
            this.rulesWindow = new RulesWindow();

            LearnerManager lm = (LearnerManager)this.Resources["learnerManager"];

            if (lm != null)
            {
                lm.PredictionUpdate += this.predictionWindow.PredictionUpdated;
                lm.PredictionUpdate += this.correctWindow.PredictionUpdated;
                lm.PredictionUpdate += this.PredictionUpdated;

                this.preferencesWindow.learnerManager = lm;
                this.rulesWindow.learnerManager = lm;
                this.learnersWindow.learnerManager = lm;

                lm.LearnersUpdate += this.learnersWindow.LearnersUpdated;
            }

            predictions = new Dictionary<string, string>();
            predictions["Activity"] = "Unknown Activity";
            predictions["Location"] = "Unknown Location";
            predictions["Social"] = "Unknown Social Context";

            AnalyticsManager.LogEvent("Application", "Jarvis Started");
        }

        private void UpdateLabel(object o)
        {
            Dictionary<String, String> d = (Dictionary<String, String>)o;

            foreach (String key in d.Keys)
            {
                String prediction = d[key];

                if (Preferences.preferences.Get("Use System Notification Area") != null &&
                    (Boolean)Preferences.preferences.Get("Use System Notification Area"))
                {
                    String newKey = key;

                    if (newKey.Equals("Social"))
                        newKey = "Social Context";

                    notifier.BalloonTipTitle = newKey + " Changed";
                    notifier.BalloonTipText = newKey + " is now " + prediction;
                    notifier.ShowBalloonTip(5000);
                }

                AnalyticsManager.LogEvent("New Prediction", key + " = " + prediction);
            }
        }

        public void PredictionUpdated(object sender, EventArgs ea, String key, String prediction)
        {
            Dictionary<String, String> d = new Dictionary<String, String>();
            d[key] = prediction;

            predictions[key] = prediction;

            if (base.CheckAccess() == true)
                UpdateLabel(d);
            else
            {
                base.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
                    new System.Threading.WaitCallback(UpdateLabel), d);
            }
        }

        public void hotkey_HotkeyPressed(object sender, EventArgs e)
        {
            this.Menu_Correct(sender, new RoutedEventArgs());

            AnalyticsManager.LogEvent("Hot Key Pressed", "Ctrl-Alt-C");
        }

        void notifier_MouseDown(object sender, WinForms.MouseEventArgs e)
        {
            if (e.Button == WinForms.MouseButtons.Right)
            {
                ContextMenu menu = (ContextMenu)this.FindResource("NotifierContextMenu");

                menu.IsOpen = true;

                AnalyticsManager.LogEvent("Menu Opened", "Jarvis Menu Activated");
            }
            else
            {
                notifier.BalloonTipTitle = "Current Context";
                notifier.BalloonTipText = "Activity: " + predictions["Activity"] + Environment.NewLine +
                                          "Location: " + predictions["Location"] + Environment.NewLine +
                                          "Social Context: " + predictions["Social"];

                notifier.ShowBalloonTip(10000);
            }
        }

        private void Menu_Unimplemented(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Unimplemented feature...");
        }

        private void Toggle_Pause(object sender, RoutedEventArgs e)
        {
            bool paused = false;

            try
            {
                paused = (bool) Preferences.preferences.Get("Paused?");
            }
            catch (NullReferenceException)
            {
                paused = false;
            }

            paused = !paused;

            sensorWindow.Activate();

            if (paused)
            {
                (sender as MenuItem).Header = "Resume Predictions";
                AnalyticsManager.LogEvent("Predictions State", "Paused");
                System.Windows.MessageBox.Show("Jarvis will no longer generate context predictions until you choose to resume them from the menu.", "Context Predictions Paused", MessageBoxButton.OK, MessageBoxImage.Information);
            }
            else
            {
                (sender as MenuItem).Header = "Pause Predictions";
                AnalyticsManager.LogEvent("Predictions State", "Active");
                System.Windows.MessageBox.Show("Jarvis has resumed generating context predictions.", "Context Predictions Resumed", MessageBoxButton.OK, MessageBoxImage.Information);
            }

            Preferences.preferences.Set("Paused?", paused);
        }

        private void Menu_Sensors(object sender, RoutedEventArgs e)
        {
            sensorWindow.Show();
            sensorWindow.Activate();

            AnalyticsManager.LogEvent("Window Opened", "Sensors");
        }

        private void Menu_About(object sender, RoutedEventArgs e)
        {
            aboutWindow.Show();
            aboutWindow.Activate();

            AnalyticsManager.LogEvent("Window Opened", "About");
        }

        private void Menu_Correct(object sender, RoutedEventArgs e)
        {
            correctWindow.Refresh();
            correctWindow.Show();
            correctWindow.Activate();

            AnalyticsManager.LogEvent("Window Opened", "Prediction Correction");
        }

        private void Menu_Predictions(object sender, RoutedEventArgs e)
        {
            predictionWindow.Show();
            predictionWindow.Activate();

            AnalyticsManager.LogEvent("Window Opened", "Predictions");
        }

        private void Menu_Undo(object sender, RoutedEventArgs e)
        {
            LearnerManager lm = (LearnerManager)this.Resources["learnerManager"];
            lm.UndoLastPrediction();

            AnalyticsManager.LogEvent("Action", "Undid Last Prediction");
        }

        private void Menu_Preferences(object sender, RoutedEventArgs e)
        {
            preferencesWindow.Show();
            preferencesWindow.Activate();

            AnalyticsManager.LogEvent("Window Opened", "Preferences");
        }

        private void Menu_Learners(object sender, RoutedEventArgs e)
        {
            learnersWindow.Show();
            learnersWindow.Activate();

            AnalyticsManager.LogEvent("Window Opened", "Learners");
        }

        private void Menu_Rules(object sender, RoutedEventArgs e)
        {
            rulesWindow.Show();
            rulesWindow.Activate();

            AnalyticsManager.LogEvent("Window Opened", "Rules");
        }

        private void Menu_Quit(object sender, RoutedEventArgs e)
        {
            sensorWindow.Show();
            sensorWindow.Activate();

            if (MessageBoxResult.Yes == System.Windows.MessageBox.Show("Are you sure that you want to quit Jarvis?", "Confirm Quit", MessageBoxButton.YesNo, MessageBoxImage.Question))
            {
                this.notifier.Visible = false;

                LearnerManager lm = (LearnerManager)this.Resources["learnerManager"];
                lm.Save();

                AnalyticsManager.LogEvent("Application", "Jarvis Quit");
                Preferences.preferences.Set("Paused?", false);

                this.Shutdown(0);
            }
        }

        internal void correctPrediction(string activity, string location, string social)
        {
            LearnerManager lm = (LearnerManager) this.Resources["learnerManager"];

            lm.SetPrediction("Activity", activity);
            lm.SetPrediction("Location", location);
            lm.SetPrediction("Social", social);

            AnalyticsManager.LogEvent("Prediction Corrected", "Activity = " + activity);
            AnalyticsManager.LogEvent("Prediction Corrected", "Location = " + location);
            AnalyticsManager.LogEvent("Prediction Corrected", "Social Context = " + social);
        }
    }
}
